
<head>
    <meta charset="UTF-8">
    <title>Excel批量處理</title>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
    <script src="https://cdn.bootcss.com/xlsx/0.11.5/xlsx.core.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/docxtemplater/3.22.5/docxtemplater.js"></script>
    <script src="https://unpkg.com/pizzip@3.0.6/dist/pizzip.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js"></script>
    <script src="https://unpkg.com/pizzip@3.0.6/dist/pizzip-utils.js"></script>

    <!-- https://blog.darkthread.net/blog/pure-js-docx-template-print/ -->
</head>
<body>
<style>
    #text{
        width:500px;
        height:1000px;
    }
</style>
<input type="file" id="excel-file">


<div>
   <textarea  id='text'>
   </textarea>
</div>
<script>


    
    //給input標籤繫結change事件，一上傳選中的.xls檔案就會觸發該函式
    
    $('#excel-file').change(function(e) {
        var files = e.target.files;
        var fileReader = new FileReader();
        fileReader.onload = function(ev) {
            try {
                var data = ev.target.result
                var workbook = XLSX.read(data, {
                    type: 'binary'
                }) // 以二進位制流方式讀取得到整份excel表格物件
                var persons = []; // 儲存獲取到的資料
            } catch (e) {
                console.log('檔案型別不正確');
                return;
            }
            // 表格的表格範圍，可用於判斷表頭是否數量是否正確
            var fromTo = '';
            // 遍歷每張表讀取
            for (var sheet in workbook.Sheets) {
                if (workbook.Sheets.hasOwnProperty(sheet)) {
                    fromTo = workbook.Sheets[sheet]['!ref'];
                    //console.log(fromTo);
                    persons = persons.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
                    //console.log(JSON.stringify(persons))
                    break; // 如果只取第一張表，就取消註釋這行
                    
                }
            }
            
            persons[0]['管片类型']= persons[0]['管片类型及封顶块位置'].split(" ")[0]
            persons[0]['管片拼装点位']= persons[0]['管片类型及封顶块位置'].split(" ")[1]
            var str="韦双区间{$隧道}隧道{$环号}环施工参数： &#13;"
                    +"1.掘进推力{$总推力(kN)}KN,刀盘转速{$刀盘转速(rpm)}r/min，刀盘扭矩{$刀盘扭矩(kN·m)}KN•m，掘进速度{$掘进速度(mm/min)}mm/min,土仓顶部土压{$上部土仓压力(bar)}bar &#13;"
                    +"2.掘进时间 &#13;"
                    +"拼装时间{$管片安装时间}&#13;"
                    +"3.掘进前水平姿态：前/后{$掘进前轴线偏差(mm)-水平(前点/后点)}；垂直姿态：前/后-{$掘进前轴线偏差(mm)-竖直(前点/后点)}；掘进后水平姿态：前/后9/11，垂直姿态：前/后-47/-47 &#13;"
                    +"4.管片拼装点位：{$管片拼装点位} &#13;"
                    +"5.管片类型：{$管片类型} &#13;"
                    +"6.同步注浆量： &#13;"
                    +"7.地质情况：泥岩 &#13;"
                    +"8.出渣量：{$实际出渣量(m3)}方 &#13;"
                    +"9.212环二次注浆，双液，1点4包水泥 &#13;";
            $.each(persons[0], function(key, value){
                if(str.indexOf("{$"+key+"}")>=0){
                    str = str.replace("{$"+key+"}",value)
                }
            });
            $("#text").html(str)
            var data = persons[0]
            generate(data)


            function loadFile(url,callback){
                PizZipUtils.getBinaryContent(url,callback);
            }
            function generate(data) {
                loadFile("sample.docx",function(error,content){
                    if (error) { throw error };

                    // The error object contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
                    function replaceErrors(key, value) {
                        if (value instanceof Error) {
                            return Object.getOwnPropertyNames(value).reduce(function(error, key) {
                                error[key] = value[key];
                                return error;
                            }, {});
                        }
                        return value;
                    }

                    function errorHandler(error) {
                        console.log(JSON.stringify({error: error}, replaceErrors));

                        if (error.properties && error.properties.errors instanceof Array) {
                            const errorMessages = error.properties.errors.map(function (error) {
                                return error.properties.explanation;
                            }).join("\n");
                            console.log('errorMessages', errorMessages);
                            // errorMessages is a humanly readable message looking like this:
                            // 'The tag beginning with "foobar" is unopened'
                        }
                        throw error;
                    }

                    var zip = new PizZip(content);
                    console.log(zip)
                    var doc;
                    try {
                        doc = new window.docxtemplater(zip, { paragraphLoop: true, linebreaks: true });
                    } catch(error) {
                        // Catch compilation errors (errors caused by the compilation of the template: misplaced tags)
                        errorHandler(error);
                    }

                    doc.setData(data);
                    try {
                        // render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
                        doc.render();
                    }
                    catch (error) {
                        // Catch rendering errors (errors relating to the rendering of the template: angularParser throws an error)
                        errorHandler(error);
                    }

                    var out=doc.getZip().generate({
                        type:"blob",
                        mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                    });
                    // Output the document using Data-URI
                saveAs(out, "output.docx");
            })
        }
            
        };
        
        // 以二進位制方式開啟檔案
        fileReader.readAsBinaryString(files[0]);
    });
    
</script>
</body>
</html>